#include "GameElementFactory.h"

GameElementFactory::GameElementFactory()
{
}

template <typename ITEM>
bool GameElementFactory::addElement(vector3<int> pos){
    return (elementCollection.size()<MAX_ELEMENTS &&
            elementCollection.insert(make_pair(pos,(GameElement*)(new ITEM(pos)))).second);
}

template <typename ITEM, GAME_ELEMENT_TYPE T>
ITEM* GameElementFactory::getElement(vector3<int> pos){
    MAP_TYPE::iterator it=elementCollection.find(pos);
    if(it!=elementCollection.end() &&
       it->second->getType()==T)
    {
        return dynamic_cast<ITEM*>(it->second);
    }
    return 0;
}

bool GameElementFactory::removeElement(vector3<int> pos){
     MAP_TYPE::iterator it=elementCollection.find(pos);
        if(it==elementCollection.end())
        return false;
        else{
            GameElement* e = it->second;
            elementCollection.erase(it);

            switch(e->getType())
            {
                case DOOR:
                    delete (dynamic_cast<ElementDoor*>(e));
                    break;
                case ENEMY:
                    delete (dynamic_cast<ElementEnemy*>(e));
                    break;
                case SWITCH:
                   delete (dynamic_cast<ElementSwitch*>(e));
                    break;
                case SPIKES:
                    delete (dynamic_cast<ElementSpikes*>(e));
                    break;
                case LADDER:
                   delete (dynamic_cast<ElementLadder*>(e));
                    break;

                default:
                break;
            }

            return true;
        }
     }


bool GameElementFactory::addDoor(vector3<int> pos){
    return addElement<ElementDoor>(pos);
}

bool GameElementFactory::addSwitch(vector3<int> pos){
    return addElement<ElementSwitch>(pos);
}

bool GameElementFactory::addSpikes(vector3<int> pos){
    return addElement<ElementSpikes>(pos);
}

bool GameElementFactory::addEnemy(vector3<int> pos){
    return addElement<ElementEnemy>(pos);
}

bool GameElementFactory::addLadder(vector3<int> pos){
    return addElement<ElementLadder>(pos);
}

ElementDoor* GameElementFactory::getDoor(vector3<int> pos){
    return getElement<ElementDoor,DOOR>(pos);
}

ElementSwitch* GameElementFactory::getSwitch(vector3<int> pos){
    return getElement<ElementSwitch,SWITCH>(pos);
}

ElementSpikes* GameElementFactory::getSpikes(vector3<int> pos){
    return getElement<ElementSpikes,SPIKES>(pos);
}

ElementLadder* GameElementFactory::getLadder(vector3<int> pos){
    return getElement<ElementLadder,LADDER>(pos);
}

ElementEnemy* GameElementFactory::getEnemy(vector3<int> pos){
    return getElement<ElementEnemy,ENEMY>(pos);
}

GameElement* GameElementFactory::getGeneric(vector3<int> pos)
{
    MAP_TYPE::iterator it=elementCollection.find(pos);
    if(it!=elementCollection.end())return it->second;
    return 0;
}

GameElement* GameElementFactory::searchNearest(vector3<int> pos){
    MAP_TYPE::iterator item = elementCollection.lower_bound(pos);
    return item==elementCollection.end()?0:(*item).second;
}
